<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>The source code</title>
  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  <style type="text/css">
    .highlight { display: block; background-color: #ddd; }
  </style>
  <script type="text/javascript">
    function highlight() {
      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
    }
  </script>
</head>
<body onload="prettyPrint(); highlight();">
  <pre class="prettyprint lang-js">var Definable = require(&quot;./Definable&quot;);

var classUtil = require(&quot;../../core/utils/class_util&quot;);

function _typeof(obj) { &quot;@babel/helpers - typeof&quot;; if (typeof Symbol === &quot;function&quot; &amp;&amp; typeof Symbol.iterator === &quot;symbol&quot;) { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj &amp;&amp; typeof Symbol === &quot;function&quot; &amp;&amp; obj.constructor === Symbol &amp;&amp; obj !== Symbol.prototype ? &quot;symbol&quot; : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(&quot;Cannot call a class as a function&quot;); } }

function _defineProperties(target, props) { for (var i = 0; i &lt; props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (&quot;value&quot; in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call &amp;&amp; (_typeof(call) === &quot;object&quot; || typeof call === &quot;function&quot;)) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(&quot;this hasn&#39;t been initialised - super() hasn&#39;t been called&quot;); } return self; }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== &quot;function&quot; &amp;&amp; superClass !== null) { throw new TypeError(&quot;Super expression must either be null or a function&quot;); } subClass.prototype = Object.create(superClass &amp;&amp; superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

<span id='qrenderer-svg-helper-ShadowManager'>/**
</span> * @class qrenderer.svg.helper.ShadowManager
 * 
 * Manages SVG shadow elements.
 * 
 * @author Zhang Wenli
 * @docauthor 大漠穷秋 damoqiongqiu@126.com
 */
function hasShadow(style) {
  // TODO: textBoxShadowBlur is not supported yet
  return style &amp;&amp; (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY || style.textShadowBlur || style.textShadowOffsetX || style.textShadowOffsetY);
}
<span id='qrenderer-svg-helper-ShadowManager-method-constructor'>/**
</span> * @method constructor ShadowManager
 * 
 * Manages SVG shadow elements.
 *
 * @param   {Number}     qrId    qrenderer instance id
 * @param   {SVGElement} svgRoot root of SVG document
 */


var ShadowManager =
/*#__PURE__*/
function (_Definable) {
  _inherits(ShadowManager, _Definable);

  function ShadowManager(qrId, svgRoot) {
    _classCallCheck(this, ShadowManager);

    return _possibleConstructorReturn(this, _getPrototypeOf(ShadowManager).call(this, qrId, svgRoot, [&#39;filter&#39;], &#39;__filter_in_use__&#39;, &#39;_shadowDom&#39;));
  }
<span id='qrenderer-svg-helper-ShadowManager-method-'>  /**
</span>   * Create new shadow DOM for fill or stroke if not exist,
   * but will not update shadow if exists.
   *
   * @param {SvgElement}  svgElement   SVG element to paint
   * @param {Displayable} displayable  qrenderer displayable element
   */


  _createClass(ShadowManager, [{
    key: &quot;addWithoutUpdate&quot;,
    value: function addWithoutUpdate(svgElement, displayable) {
      if (displayable &amp;&amp; hasShadow(displayable.style)) {
        // Create dom in &lt;defs&gt; if not exists
        var dom;

        if (displayable._shadowDom) {
          // Gradient exists
          dom = displayable._shadowDom;
          var defs = this.getDefs(true);

          if (!defs.contains(displayable._shadowDom)) {
            // _shadowDom is no longer in defs, recreate
            this.addDom(dom);
          }
        } else {
          // New dom
          dom = this.add(displayable);
        }

        this.markUsed(displayable);
        var id = dom.getAttribute(&#39;id&#39;);
        svgElement.style.filter = &#39;url(#&#39; + id + &#39;)&#39;;
      }
    }
<span id='qrenderer-svg-helper-ShadowManager-method-'>    /**
</span>     * Add a new shadow tag in &lt;defs&gt;
     *
     * @param {Displayable} displayable  qrenderer displayable element
     * @return {SVGFilterElement} created DOM
     */

  }, {
    key: &quot;add&quot;,
    value: function add(displayable) {
      var dom = this.createElement(&#39;filter&#39;); // Set dom id with shadow id, since each shadow instance
      // will have no more than one dom element.
      // id may exists before for those dirty elements, in which case
      // id should remain the same, and other attributes should be
      // updated.

      displayable._shadowDomId = displayable._shadowDomId || this.nextId++;
      dom.setAttribute(&#39;id&#39;, &#39;qr&#39; + this._qrId + &#39;-shadow-&#39; + displayable._shadowDomId);
      this.updateDom(displayable, dom);
      this.addDom(dom);
      return dom;
    }
<span id='qrenderer-svg-helper-ShadowManager-method-'>    /**
</span>     * Update shadow.
     *
     * @param {Displayable} displayable  qrenderer displayable element
     */

  }, {
    key: &quot;update&quot;,
    value: function update(svgElement, displayable) {
      var style = displayable.style;

      if (hasShadow(style)) {
        var that = this;
        Definable.prototype.update.call(this, displayable, function () {
          that.updateDom(displayable, displayable._shadowDom);
        });
      } else {
        // Remove shadow
        this.remove(svgElement, displayable);
      }
    }
<span id='qrenderer-svg-helper-ShadowManager-property-'>    /**
</span>     * Remove DOM and clear parent filter
     */

  }, {
    key: &quot;remove&quot;,
    value: function remove(svgElement, displayable) {
      if (displayable._shadowDomId != null) {
        this.removeDom(svgElement);
        svgElement.style.filter = &#39;&#39;;
      }
    }
<span id='qrenderer-svg-helper-ShadowManager-method-'>    /**
</span>     * Update shadow dom
     *
     * @param {Displayable} displayable  qrenderer displayable element
     * @param {SVGFilterElement} dom DOM to update
     */

  }, {
    key: &quot;updateDom&quot;,
    value: function updateDom(displayable, dom) {
      var domChild = dom.getElementsByTagName(&#39;feDropShadow&#39;);

      if (domChild.length === 0) {
        domChild = this.createElement(&#39;feDropShadow&#39;);
      } else {
        domChild = domChild[0];
      }

      var style = displayable.style;
      var scaleX = displayable.scale ? displayable.scale[0] || 1 : 1;
      var scaleY = displayable.scale ? displayable.scale[1] || 1 : 1; // TODO: textBoxShadowBlur is not supported yet

      var offsetX;
      var offsetY;
      var blur;
      var color;

      if (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY) {
        offsetX = style.shadowOffsetX || 0;
        offsetY = style.shadowOffsetY || 0;
        blur = style.shadowBlur;
        color = style.shadowColor;
      } else if (style.textShadowBlur) {
        offsetX = style.textShadowOffsetX || 0;
        offsetY = style.textShadowOffsetY || 0;
        blur = style.textShadowBlur;
        color = style.textShadowColor;
      } else {
        // Remove shadow
        this.removeDom(dom, style);
        return;
      }

      domChild.setAttribute(&#39;dx&#39;, offsetX / scaleX);
      domChild.setAttribute(&#39;dy&#39;, offsetY / scaleY);
      domChild.setAttribute(&#39;flood-color&#39;, color); // Divide by two here so that it looks the same as in canvas
      // See: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-shadowblur

      var stdDx = blur / 2 / scaleX;
      var stdDy = blur / 2 / scaleY;
      var stdDeviation = stdDx + &#39; &#39; + stdDy;
      domChild.setAttribute(&#39;stdDeviation&#39;, stdDeviation); // Fix filter clipping problem

      dom.setAttribute(&#39;x&#39;, &#39;-100%&#39;);
      dom.setAttribute(&#39;y&#39;, &#39;-100%&#39;);
      dom.setAttribute(&#39;width&#39;, Math.ceil(blur / 2 * 200) + &#39;%&#39;);
      dom.setAttribute(&#39;height&#39;, Math.ceil(blur / 2 * 200) + &#39;%&#39;);
      dom.appendChild(domChild); // Store dom element in shadow, to avoid creating multiple
      // dom instances for the same shadow element

      displayable._shadowDom = dom;
    }
<span id='qrenderer-svg-helper-ShadowManager-method-'>    /**
</span>     * Mark a single shadow to be used
     *
     * @param {Displayable} displayable displayable element
     */

  }, {
    key: &quot;markUsed&quot;,
    value: function markUsed(displayable) {
      if (displayable._shadowDom) {
        Definable.prototype.markUsed.call(this, displayable._shadowDom);
      }
    }
  }]);

  return ShadowManager;
}(Definable);

var _default = ShadowManager;
module.exports = _default;</pre>
</body>
</html>
